#ifndef ObjList_First
#define ObjList_First
#ifdef __GNUG__
#pragma interface
#endif

#include "SeqColl.h"

class ObjList;
class ObjListIter;
class RevObjListIter;

//---- ObjLink -----------------------------------------------------------------

class ObjLink: public Object {
friend ObjList;
friend ObjListIter;
friend RevObjListIter;
protected:
	ObjLink()
		{ obj= 0; next= this; prev= this; }
public:
	MetaDef(ObjLink);
	ObjLink(Object *op, ObjLink *lnk);

	void FreeAll();

	Object *GetObject()
		{ return obj; }
	void SetObject(Object *op)
		{ obj= op; }
	ObjLink *Next()
		{ return next; }
	ObjLink *Prev()
		{ return prev; }

private:
	ObjLink *next, *prev;
	Object *obj;
};

//---- ObjList -----------------------------------------------------------------

class ObjList: public SeqCollection {
friend ObjListIter;
friend RevObjListIter;
public:
	MetaDef(ObjList);
	ObjList();
	~ObjList();

	void InitNew();
	void Empty(int);
	void FreeAll();
		
	//---- accessing
	Iterator *MakeIterator(bool dir= cIterForward, void *placement= 0);
protected:
	//---- primitives
	Object *primAddAt(Object *op, int idx);
	Object *primRemoveAt(int idx);
	Object *primPutAt(Object *op, int idx);
	Object *primAt(int idx);
	Object *primIndexOf(Object *op, int offset, int *idx);
	Object *primIndexOfPtr(Object *op, int offset, int *idx);
	Object *AddRelative(Object *op, EqualType eq, int offset, Object *to);
	Object *RemoveRelative(Object *op, EqualType eq, int offset);

	virtual ObjLink *NewLink(Object *op, ObjLink *prev);
	virtual void DeleteLink(ObjLink *lnk);

	//---- implementation
	ObjLink *FindLink(Object *op, int &idx);
	ObjLink *FindLinkPtr(Object *op, int &idx);
	ObjLink *LinkAt(int idx);
	ObjLink *LinkByOffset(ObjLink *lnk, int offset);
	void RemoveLink(ObjLink *lnk);
	void InsertLink(Object *op, ObjLink *lnk);
protected:
	ObjLink *head;
};

//---- ObjListIter -------------------------------------------------------------

class ObjListIter: public Iterator {
friend ObjList;
public:
	ObjListIter(ObjList *s);
	~ObjListIter();

	Object* operator()();
	void Reset();
protected:
	Container *GetContainer();
	void Detach();
	void OnEmpty();
	void OnRemove(ObjLink *lnk);
protected:
	ObjList *list;
	ObjLink *ce;
};

//---- RevObjListIter ----------------------------------------------------------

class RevObjListIter: public ObjListIter {
public:
	RevObjListIter(ObjList *s);
		
	Object* operator()();
protected:
	void OnRemove(ObjLink *lnk);
};

#endif

